#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include "processo.h"
#include "process_manager.h"
#include "in_out.h"

/*Sempre que um processo for criado pelo process Manager, essa função será chamada*/


int main(int argc, char**argv){
	
	/*Inicializaçoes das variaveis.*/
	id_processos = 0;
	contador_global = 1;
	qtd_processos_bloqueados = 0;
	qtd_processos_prontos = 0;
	qtd_processos_criados = 0;
	
	/*
	 *Determina o tipo de escalonador através do parametro passado na linha de comando.
	 * 1 - Prioridade
	 * 2 - Tempo
	 * 3 - Aleatório 
	 **/
	
	//verifica se o número de argumentos é válido. Devem ter somente 2 argumento: nome do programa e tipo de escalonador
	if(argc > 2){
		printf("Linha de comando inválida! A forma correta é: ./nome_programa tipo_escalonador");
		return;
	}
	//verifica se o segundo argumento passado é um inteiro válido. 1 <= tipo_escalonador <= 3
	else{
		tipo_escalonador = atoi(argv[1]);
		if(tipo_escalonador < 1 || tipo_escalonador > 3){
			printf("Linha de comando inválida! O valor de tipo_escalonador deve ser maior que 0 e menor que 4.");
			return;
		}
	}
	
	
	/*Declaracao de variaveis do process_manager*/
	char pipe;
	int pid=0, x=1;
	
	processo_simulado *init;
	/*
	
	  Cria tabela de processos, 
	  lista de processos prontos e 
	  lista de processos bloqueados.
	
	*/
	
	tabela_processos = alocar_tabela_processos(100);
	processos_bloqueados = alocar_tabela_processos(100);
	processos_prontos = alocar_tabela_processos(100);
	
	/*
	  O Process_manager, nada mais é que o primeiro processo a ser chamado,
	  Em sua lista de instruções, ele guarda os dados do arquivo init.
	  Em outras palavras, podemos dizer que o init é o primeiro processo a ser
	  criado pelo sistema, sendo assim, pai de todos os outros.	
	*/
	init = iniciar_processo("init",pid);
	
	/*
	  CPU é uma estrutura de processos, pois ela recebe a cada momento, o processo em 
	  execução. Portanto, no inicio do programa, recebe o unico processo criado até então,
	  que é o init (ou process manager).
	*/
	cpu = init;
	
	/*Aloca o processo init na tabela de processos*/
	adiciona_processo_pcb(cpu);
	
	/*Aloca o processo init na lista de processos prontos*/
	adiciona_processo_lista_prontos(cpu);
	
	/*
	  Recebe os comandos digitados no comander e executa-os.
	*/
	
	while(x==1){
		/*Se o processo ja tiver acabado, encerra-o.*/
		if(cpu->contador_programa == cpu->tamanho-1) encerrar_processo();
		
		printf("Digite um comando:\n");
		scanf("%c",&pipe);
		
		switch(pipe){
			
		   /*Processo executa função*/
		   case 'q':
             /*
               Será definido um certo numero de 'clocks'. Quando o contador
               atingir esse numero, haverá uma IO, então, será necessario 
               bloquear o processo que estiver na cpu no momento. Escalonar. 
             */
             if(contador_global % 5 == 0){
				
				bloquear_processo();		
				escalonar();
			 
			 }
             printf("Fim de uma unidade de tempo\n");
             executa_instrucao();
             break;

           case 'u':
             printf("Desbloqueie o primeiro processo simulado que está na fila de bloqueados.\n");
             desbloquear_processo();
             break;

           case'p':
             processo_reporter();
             break;
  
           case 't':
             printf("FIM\n");
			 x++;	
             break;
		   
		   default:
             printf("\nFALHA!!!!!!!!\n");
             break; 
        }
        
        /*Incrementa o contador global de programa.*/
        contador_global++;
	}
}
